package com.hkd.gateway.filter;

import com.hkd.common.api.constants.AuthConstants;
import com.hkd.utils.RSAUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * @author HKD
 * @date 2022/8/21 23:04
 */
@Component
public class JwtTokenFilter implements GlobalFilter, Ordered {
    /**
     * 放行
     */
    private String[] skipAuthUrls={"/auth/oauth/token","/main/v2/api-docs","/auth/v2/api-docs",};


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath();
        System.out.println(url);
        //跳过不需要验证的路径
        if (null!=skipAuthUrls&& Arrays.asList(skipAuthUrls).contains(url)){
            return chain.filter(exchange);
        }
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (!StringUtils.hasText(token)){
            return returnAuthFail(exchange,"请登录");
        }else {
                Claims jwt = getTokenBody(token);
                ServerHttpRequest oldRequest = exchange.getRequest();
                URI uri = oldRequest.getURI();
                ServerHttpRequest newRequest = oldRequest.mutate().uri(uri).build();

                HttpHeaders headers = new HttpHeaders();
                headers.putAll(exchange.getRequest().getHeaders());
                headers.remove("Authorization");
                headers.set(AuthConstants.JWT_USER_Id,jwt.get(AuthConstants.JWT_USER_Id,String.class));

               newRequest= new ServerHttpRequestDecorator(newRequest){
                    @Override
                    public HttpHeaders getHeaders() {
                        HttpHeaders httpHeaders = new HttpHeaders();
                        httpHeaders.putAll(headers);
                        return httpHeaders;
                    }
                };
                return chain.filter(exchange.mutate().request(newRequest).build());
        }
    }

    /**
     * 返回校验失败
     *
     * @param exchange
     * @return
     */
    private Mono<Void> returnAuthFail(ServerWebExchange exchange,String message) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
        String resultData = "{\"status\":\"-1\",\"msg\":"+message+"}";
        byte[] bytes = resultData.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
        return exchange.getResponse().writeWith(Flux.just(buffer));
    }

    private static Claims getTokenBody(String token){
        return Jwts.parser()
                .setSigningKey(RSAUtil.getPublicKey())
                .parseClaimsJws(token)
                .getBody();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
